package com.qf.ability.gateway.filter;

import com.ken.event.action.apply.producer.EventTemplate;
import com.qf.ability.gateway.utils.ResponseUtils;
import com.qf.commons.base.result.Codes;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * 抢红包的过滤器 - 局部过滤器
 * author Ken
 * create_time 2022/12/6
 */
@Component
@Slf4j
public class RobRedFilter extends AbstractGatewayFilterFactory implements GatewayFilter, Ordered {

    /**
     * 抢红包的lua脚本
     */
    private String robLua = "--抢红包的脚本，参数 KEYS【红包id】 ARGV【用户id】\n" +
            "local redid = KEYS[1]\n" +
            "local uid = ARGV[1]\n" +
            "\n" +
            "--拼接红包的key\n" +
            "local key = \"red-envlopse-\"..redid\n" +
            "\n" +
            "--判断红包的key是否存在\n" +
            "local result = redis.call('exists', key)\n" +
            "if result == 0 then\n" +
            "    --红包信息未查询到\n" +
            "    return -1\n" +
            "end\n" +
            "\n" +
            "--查询红包中剩余的份数\n" +
            "local hasCount = tonumber(redis.call('hget', key, 'hasCount'))\n" +
            "if hasCount == 0 then\n" +
            "    --红包已经抢完了\n" +
            "    return -2\n" +
            "end\n" +
            "\n" +
            "local userExists = redis.call('hexists', key, 'user-'..uid)\n" +
            "if userExists == 1 then \n" +
            "    --当前用户已经抢过\n" +
            "    return -3\n" +
            "end\n" +
            "\n" +
            "--获取剩余积分\n" +
            "local hasScore = tonumber(redis.call('hget', key, 'hasScore'))\n" +
            "--红的红包类型\n" +
            "local type = tonumber(redis.call('hget', key, 'type'))\n" +
            "--当前抢到的积分数\n" +
            "local robScore = 0\n" +
            "\n" +
            "if hasCount == 1 then\n" +
            "   --最后一个红包\n" +
            "   robScore = hasScore \n" +
            "else\n" +
            "   --不是最后一个红包\n" +
            "   if type == 0 then\n" +
            "       -- 固定红包\n" +
            "       robScore = hasScore / hasCount\n" +
            "   else \n" +
            "       local time = redis.call('time')\n" +
            "       -- 设置随机数的种子\n" +
            "       math.randomseed(time[1] * 1000000 + time[2])\n" +
            "       -- 随机红包\n" +
            "       robScore = math.random(hasScore / hasCount * 2 - 1)\n" +
            "   end \n" +
            "end\n" +
            "\n" +
            "--回设redis中的相关参数\n" +
            "redis.call('hset', key, 'user-'..uid, robScore)\n" +
            "redis.call('hset', key, 'hasScore', hasScore - robScore)\n" +
            "redis.call('hset', key, 'hasCount', hasCount - 1)\n" +
            "\n" +
            "--返回抢到的积分数\n" +
            "return robScore ";

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public GatewayFilter apply(Object config) {
        return this;
    }

    /**
     * 局部过滤器的过滤方法
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.debug("[rob red filter] 抢红包的局部过滤器触发！！！");
        ServerHttpRequest request = exchange.getRequest();
        //1、获得红包id
        String redid = request.getQueryParams().getFirst("redid");

        //2、用户id
//        String userJson = request.getHeaders().getFirst("userJson");
//        BaseUser user = null;
//        try {
//            userJson = URLDecoder.decode(userJson, "UTF-8");
//            user = JSON.parseObject(userJson, BaseUser.class);
//        } catch (UnsupportedEncodingException e) {
//            throw new RuntimeException(e);
//        }
//        Long uid = user.getId();
        //模拟生成的用户id
        Long uid = (long)(Math.random() * 100000);

        //3、执行抢红包的脚本
        Long robScore = redisTemplate.execute(new DefaultRedisScript<>(robLua, Long.class),
                Collections.singletonList(redid),
                uid + "");

        log.debug("[rob red filter] 抢红包的lua脚本执行的结果 - {}", robScore);

        //红包信息在redis中不存在
        if (robScore <= 0) {
           return ResponseUtils.result(exchange, Codes.SUCC, robScore, HttpStatus.OK);
        }

        //红包已经抢到，将信息通过事件总线发送给后端的红包服务，修改数据库
        Map<String, Long> map = new HashMap<>();
        map.put("redid", Long.valueOf(redid));
        map.put("uid", uid);
        map.put("robScore", robScore);
        EventTemplate.sendQuickly("rob-red", map);

        return ResponseUtils.result(exchange, Codes.SUCC, robScore, HttpStatus.OK);
    }

    @Override
    public String name() {
        return "robRedFilter";
    }


    @Override
    public int getOrder() {
        return -1;
    }
}
